home *** CD-ROM | disk | FTP | other *** search
/ Stone Design / Stone Design.iso / Stone_Friends / Wave / WavesWorld / Source / IBPalettes / WW3DKit / WWLightInspectorCamera.m < prev    next >
Encoding:
Text File  |  1995-03-22  |  13.3 KB  |  419 lines

  1. // copyright 1993 Michael B. Johnson; some portions copyright 1994, MIT
  2. // see COPYRIGHT for reuse legalities
  3. //
  4.  
  5.  
  6. /* this camera is intended to be used in conjunction with some other
  7. camera "sourceCamera" for controlling that camera's lights.  This
  8. camera has a notion of the "sceneShape", which is the world shape from
  9. the other camera.  It interrogates this shape for it's bounding box
  10. and uses it to draw a box where the shape is.  It draws this box (in
  11. wireframe) and then it draws a plane twice the size of the box in each
  12. of the three orthogonal axes.
  13. */
  14.  
  15. #import "WW3DLight.h"
  16. #import "WW3DShader.h"
  17. #import "WWLightInspectorCamera.h"
  18. #import "WWLightInspectorShape.h"
  19. #import "WWDADLightView.h"
  20.  
  21. @implementation WWLightInspectorCamera
  22.  
  23. + initialize { return [WWLightInspectorCamera setVersion:1], self; }
  24.  
  25. - initFrame:(const NXRect *)r 
  26. {
  27.    RtPoint  fromP = {5, 5, -10.0}, toP = {0, 0, 0};
  28.    id       aShape, secondLevelShape, thirdLevelShape;
  29.    const char  *WDRAG_PBTYPE[] = { NXAsciiPboardType, NULL};
  30.  
  31.  
  32.    [super initFrame:r];
  33.    [self registerForDraggedTypes:WDRAG_PBTYPE count:1];
  34.  
  35.    renderStyle = N3D_SmoothSolids;
  36.    movingRenderStyle = N3D_WireFrame;
  37.  
  38.    scaleUpFactor = 1.05;
  39.    scaleDownFactor = 0.95;
  40.    translateXFactor = 0.025;
  41.    translateYFactor = 0.025;
  42.    translateZFactor = 0.05;
  43.    epsilon = 4.0;
  44.    selectionWidthEpsilon = 8.0;
  45.    selectionHeightEpsilon = 8.0;
  46.    showSelectedShape = NO;
  47.    drawOriginForSelectedShape = NO;
  48.    
  49.    // setup 3D camera stuff
  50.    [self setEyeAt:fromP toward:toP roll:0.0];
  51.  
  52.   //[self setupDefaultLights];
  53.   // !!! need to get lights from sourceCamera
  54.   // here in init, though, we probably don't have any...
  55.  
  56.   // setup some initial global rendering state
  57.   // note that this fucks up the 3DWell - yikes!
  58.   //[self setSurfaceTypeForAll:renderStyle chooseHider:YES];    
  59.   lowRezTesselationVector[0] = lowRezTesselationVector[1] = 4.0;
  60.   tesselationVector[0] = tesselationVector[1] = 8.0;
  61.   //RiGeometricApproximation(RI_TESSELATION, RI_PARAMETRIC, tesselationVector, RI_NULL);
  62.  
  63.   // stick in a reasonable shader
  64.   theShader=[[WW3DShader alloc] init];
  65.   [theShader setUseColor:YES];
  66.   [theShader setColor:ribColor];
  67.   [(N3DShader *)theShader setShader:"plastic"];
  68.  
  69.   // stick in a reasonable reference shape
  70.   aShape = [[N3DShape alloc] init];
  71.   [aShape setShapeName:NXCopyStringBuffer("lightWorld")];
  72.   [[self setWorldShape:aShape] free]; // free the default world shape
  73.  
  74.   secondLevelShape = [[N3DShape alloc] init];
  75.   [[self worldShape] linkDescendant:secondLevelShape];
  76.   thirdLevelShape = [[WWLightInspectorShape alloc] init];
  77.   [aShape setShapeName:NXCopyStringBuffer("boundingBoxOfWellWorld")];
  78.   //[aShape calculateBoundingBox];
  79.   [secondLevelShape linkDescendant:thirdLevelShape];
  80.  
  81.   // now when we add lights as descendants of the worldShape, they
  82.   // will illuminate the bounding box of the well world...
  83.  
  84.   [self setSurfaceTypeForAll:N3D_SmoothSolids chooseHider:YES];
  85.  
  86.   theRotator = [[N3DRotator alloc] initWithCamera:self];
  87.   [theRotator setRotationAxis:N3D_AllAxes];
  88.   trackballAffects = WW_TRACKBALL_CAMERA;
  89.  
  90.   return self;
  91. }
  92.  
  93. // the receptor gets sent this message when the object is dragged into
  94. // the File window, and when it is unarchived from the nib file.
  95. - awake
  96. {
  97.   const char  *WDRAG_PBTYPE[] = { NXAsciiPboardType, NULL};
  98.  
  99.  
  100.   [super awake];
  101.   [self registerForDraggedTypes:WDRAG_PBTYPE count:1];
  102.  
  103.   // everything else has just been unarchived...
  104.  
  105.   theRotator = [[N3DRotator alloc] initWithCamera:self];
  106.   [theRotator setRotationAxis:N3D_AllAxes];
  107.   trackballAffects = WW_TRACKBALL_CAMERA;
  108.  
  109.   return self;
  110. }
  111.  
  112. - free
  113.  
  114. {
  115.   [self unregisterDraggedTypes];
  116.   return [super free];
  117. }
  118.  
  119.  
  120. /////////////////////// 
  121. // 3D stuff
  122. /////////////////////// 
  123. #define ACTIVEBUTTONMASK (NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK|NX_ALTERNATEMASK|NX_CONTROLMASK|NX_COMMANDMASK)
  124. - mouseDown:(NXEvent *)theEvent
  125. {
  126.   int        oldMask;
  127.   //NXPoint    p, last, start;
  128.   //NXRect     visibleRect, oldRegion;
  129.   NXPoint    start;
  130.   RtPoint    myEyePoint, 
  131.              previousEyePoint, previousViewPoint;
  132.   float      previousRoll;
  133.  
  134.  
  135.   dMouse.x = 0.0;
  136.   dMouse.y = 0.0;
  137.  
  138.   // track the mouse until a mouseUp event occurs, updating the display
  139.   // as tracking happens.
  140.   [self lockFocus];
  141.   oldMask = [window addToEventMask:ACTIVEBUTTONMASK];
  142.   
  143.   // switch to the N3D_WireFrame surface type
  144.   [self setSurfaceTypeForAll:movingRenderStyle chooseHider:YES];    
  145.   RiGeometricApproximation(RI_TESSELATION, RI_PARAMETRIC, lowRezTesselationVector, RI_NULL);
  146.   
  147.   oldMouse = theEvent->location;
  148.   [self convertPoint:&oldMouse fromView:nil];
  149.   start = oldMouse;
  150.  
  151.   // when the alt key is depressed, we scale the worldShape up or down, depending on mouse movement.
  152.   // otherwise, we rotate the worldShape using the virtual trackball
  153.  
  154.   while (1)
  155.   { newMouse = theEvent->location;
  156.     [self convertPoint:&newMouse fromView:nil];
  157.     dMouse.x = newMouse.x - oldMouse.x;
  158.     dMouse.y = newMouse.y - oldMouse.y;
  159.     if (dMouse.x != 0.0 || dMouse.y != 0.0) 
  160.     {  if (theEvent->flags & NX_ALTERNATEMASK)
  161.        {  switch (trackballAffects)
  162.       {  case WW_TRACKBALL_WORLD_SHAPE:
  163.          [worldShape translate:0.0 :0.0 :(translateZFactor * dMouse.y)];
  164.          break;
  165.          case WW_TRACKBALL_CAMERA:
  166.          // need to change Eye point
  167.          [self moveEyeBy:0.0 :0.0 :(-1. * (translateZFactor * dMouse.y))];
  168.          break;
  169.       }
  170.        }
  171.        else
  172.        {  
  173.          if (theEvent->flags & NX_COMMANDMASK)
  174.              {  switch (trackballAffects)
  175.           {  case WW_TRACKBALL_WORLD_SHAPE:
  176.             [worldShape translate:(translateXFactor * dMouse.x) 
  177.                                          :(translateYFactor * dMouse.y) :0.0];
  178.             break;
  179.               case WW_TRACKBALL_CAMERA:
  180.                     [self moveEyeBy:(-1. * (translateXFactor * dMouse.x)) 
  181.                              :(-1. * (translateYFactor * dMouse.y)) :0.0];
  182.             break;
  183.             }
  184.          }
  185.              else
  186.              {  [theRotator trackMouseFrom:&oldMouse to:&newMouse rotationMatrix:rmat andInverse:irmat];
  187.                 switch (trackballAffects)
  188.         {  case WW_TRACKBALL_WORLD_SHAPE:
  189.                [worldShape concatTransformMatrix:rmat premultiply:YES];
  190.                        break;
  191.            case WW_TRACKBALL_CAMERA:
  192.                [self getEyeAt:&previousEyePoint toward:&previousViewPoint roll:&previousRoll];   
  193.                        myEyePoint[0] = previousEyePoint[0] + (-1. * (translateXFactor * dMouse.x)); 
  194.                        myEyePoint[1] = previousEyePoint[1] + (-1. * (translateYFactor * dMouse.y)); 
  195.                        myEyePoint[2] = previousEyePoint[2];
  196.                [self setEyeAt:myEyePoint toward:previousViewPoint roll:previousRoll];   
  197.  
  198.                        break;
  199.         }
  200.          } 
  201.        }
  202.        [self display];
  203.        NXPing();
  204.     }
  205.     theEvent = [NXApp getNextEvent:ACTIVEBUTTONMASK];
  206.     if (theEvent->type == NX_MOUSEUP)
  207.     {  break;
  208.     }
  209.     else
  210.     {  oldMouse = newMouse;
  211.     }
  212.   }
  213.  
  214.   // check to see if we should go off and render (need a minimum image size, like 16x16)...
  215.  
  216.   [self setSurfaceTypeForAll:renderStyle chooseHider:YES];    
  217.   RiGeometricApproximation(RI_TESSELATION, RI_PARAMETRIC, tesselationVector, RI_NULL);
  218.  
  219.   [self display];
  220.   [self unlockFocus];
  221.   [window setEventMask:oldMask];
  222.   [window flushWindow];
  223.  
  224.   return self;
  225. }
  226.  
  227. - (BOOL)acceptsFirstResponder { return YES; }
  228.  
  229. - (BOOL)acceptsFirstMouse { return YES; }
  230.  
  231. - (int)trackballAffects { return trackballAffects; }
  232. - takeTrackballAffectsFromMatrix:sender
  233. {
  234.   int  newVal = [[sender selectedCell] tag];
  235.  
  236.  
  237.   switch (newVal)
  238.   {  case WW_TRACKBALL_WORLD_SHAPE:
  239.      trackballAffects = newVal;
  240.          [self setUsePreTransformMatrix:NO];
  241.      break;
  242.      case WW_TRACKBALL_CAMERA:
  243.      // we assume that [self usesPreTransformMatrix] returns YES...
  244.      trackballAffects = newVal;
  245.          [self setUsePreTransformMatrix:YES];
  246.       break;
  247.      default:
  248.      NXLogError("%d is an invalid value for trackballAffects.\n", newVal);
  249.      } 
  250.  
  251.  
  252.   return self;
  253. }
  254.  
  255. - (int)trackballXYZ 
  256.   N3DAxis  theAxis  = [theRotator rotationAxis];
  257.   int      theAxisInt = -1;
  258.  
  259.  
  260.   if (theAxis == N3D_AllAxes) { theAxisInt = 0; }
  261.  
  262.   if (theAxis == N3D_XAxis) { theAxisInt = 1; }
  263.   if (theAxis == N3D_YAxis) { theAxisInt = 2; }
  264.   if (theAxis == N3D_ZAxis) { theAxisInt = 3; }
  265.  
  266.   if (theAxis == N3D_XYAxes) { theAxisInt = 4; }
  267.   if (theAxis == N3D_XZAxes) { theAxisInt = 5; }
  268.   if (theAxis == N3D_YZAxes) { theAxisInt = 6; }
  269.  
  270.   return theAxisInt;
  271. }
  272.  
  273. - takeTrackballXYZFromMatrix:sender
  274. {
  275.   int  newVal = [[sender selectedCell] tag];
  276.  
  277.   switch (newVal)
  278.   {  case 0:
  279.      [theRotator setRotationAxis:N3D_AllAxes];
  280.      break;
  281.      case 1:
  282.      [theRotator setRotationAxis:N3D_XAxis];
  283.      break;
  284.      case 2:
  285.      [theRotator setRotationAxis:N3D_YAxis];
  286.      break;
  287.      case 3:
  288.      [theRotator setRotationAxis:N3D_ZAxis];
  289.      break;
  290.      case 4:
  291.      [theRotator setRotationAxis:N3D_XYAxes];
  292.      break;
  293.      case 5:
  294.      [theRotator setRotationAxis:N3D_XZAxes];
  295.      break;
  296.      case 6:
  297.      [theRotator setRotationAxis:N3D_YZAxes];
  298.      break;
  299.      default:
  300.      NXLogError("%d is an invalid value for trackballXYZ.\n", newVal);
  301.      } 
  302.   return self;
  303. }
  304.  
  305.  
  306. - (NXColor) backgroundColor     { return backgroundColor; }
  307. - setBackgroundColor:(NXColor)c { backgroundColor = c; [self display]; return self; }
  308.  
  309. ////////////////////////////////////////////////////////////////////
  310. //            Dragging stuff
  311. ///////////////////////////////////////////////////////////////////
  312.  
  313.  
  314. - (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender
  315. {
  316.     if ([[sender draggingSource] respondsTo:@selector(lightType)])
  317.     {  return NX_DragOperationCopy;
  318.     }
  319.     return NX_DragOperationNone;
  320. }
  321.  
  322. - (NXDragOperation)draggingUpdated:(id <NXDraggingInfo>)sender
  323. {
  324.     if ([[sender draggingSource] respondsTo:@selector(lightType)])
  325.     {  return NX_DragOperationCopy;
  326.     }
  327.     return NX_DragOperationNone;
  328. }
  329.  
  330. - draggingExited:sender { return self; }
  331. - (BOOL)prepareForDragOperation:sender  { return YES; }
  332.  
  333. - (BOOL)performDragOperation:sender
  334. {
  335.     RtPoint fromPoint = {1, 1, -1};
  336.     RtPoint toPoint = {0, 0, 0};
  337.     RtFloat  coneAngle = 30.0, 
  338.              coneDelta = 5.0, 
  339.              beamDistribution = 2.0, 
  340.              intensity = 0.7;
  341.     id       newLight;
  342.     NXEvent  *event = [NXApp currentEvent];
  343.     NXPoint  locationInWindow;
  344.     NXRect   myFrame;
  345.  
  346.  
  347.     locationInWindow.x = event->location.x;
  348.     locationInWindow.y = event->location.y;
  349.     NXLogError("locationInWindow == (%f %f)\n", locationInWindow.x, locationInWindow.y);
  350.     [self convertPoint:&locationInWindow fromView:[[self window] contentView]];
  351.     NXLogError("location in this view == (%f %f)\n", locationInWindow.x, locationInWindow.y);
  352.     [self getFrame:&myFrame];
  353.     NXLogError("my frame is (%f %f) and starts at (%f %f)\n", 
  354.                myFrame.size.width, myFrame.size.height, myFrame.origin.x, myFrame.origin.y);
  355.     NXLogError("normalized, the drop happened at (%f %f)\n", 
  356.                (locationInWindow.x/myFrame.size.width), (locationInWindow.y/myFrame.size.height)); 
  357.  
  358.     if ([[sender draggingSource] respondsTo:@selector(lightType)])
  359.     {  // send lightType, malloc up a new one, figure out where the mouse is and drop the light there
  360.        switch ((int)[[sender draggingSource] lightType])
  361.        {  case ((int)N3D_PointLight):    newLight = [[WW3DLight alloc] init];
  362.                                      [newLight makePointFrom:fromPoint intensity:intensity];
  363.                                      [newLight translate:N3D_XComp(fromPoint) :N3D_YComp(fromPoint) :N3D_ZComp(fromPoint)];
  364.                                      [[self worldShape] linkDescendant:newLight];
  365.                                       break;
  366.           case ((int)N3D_DistantLight):  newLight = [[WW3DLight alloc] init];
  367.                                      [newLight makeDistantFrom:fromPoint to:toPoint intensity:intensity];
  368.                                      [newLight translate:N3D_XComp(fromPoint) :N3D_YComp(fromPoint) :N3D_ZComp(fromPoint)];
  369.                                      [[self worldShape] linkDescendant:newLight];
  370.                                      break;
  371.           case ((int)N3D_SpotLight):     newLight = [[WW3DLight alloc] init];
  372.                                      [newLight makeSpotFrom:fromPoint to:toPoint 
  373.                                                    coneAngle:coneAngle coneDelta:coneDelta 
  374.                                                    beamDistribution:beamDistribution 
  375.                                                    intensity:intensity];
  376.                                      [newLight translate:N3D_XComp(fromPoint) :N3D_YComp(fromPoint) :N3D_ZComp(fromPoint)];
  377.                                         [[self worldShape] linkDescendant:newLight];
  378.                                      break;
  379.           default:                       newLight = [[WW3DLight alloc] init];
  380.                                      [[self worldShape] linkDescendant:newLight];
  381.                                      break;
  382.         }
  383.         return YES;
  384.     }
  385.     return NO;
  386. }
  387.  
  388.  
  389. - concludeDragOperation:sender {  return self; }
  390.  
  391. #define typeVector "fff[2f][2f]"
  392. #define typeValues &translateXFactor, &translateYFactor, &translateZFactor, &lowRezTesselationVector, &tesselationVector
  393.  
  394.  
  395. - read:(NXTypedStream *)stream {
  396.     int version;
  397.     [super read:stream];
  398.  
  399.     version = NXTypedStreamClassVersion(stream,"WWLightCamera");
  400.     if (version == 0) NXReadTypes(stream,"i",&version), version=1;
  401.     if (version == 1)
  402.     {  NXReadTypes(stream, typeVector, typeValues);
  403.        backgroundColor = NXReadColor(stream);
  404.     }
  405.     return self;
  406. }
  407.  
  408. - write:(NXTypedStream *)stream 
  409. {
  410.     [super write:stream];
  411.     NXWriteTypes(stream, typeVector, typeValues);
  412.     NXWriteColor(stream, backgroundColor);
  413.     return self;
  414. }
  415.  
  416.  
  417. @end
  418.